#include <QSettings>
#include <QTextCodec>

#include "qlspluginsmanagerappfwk.h"
#include "qlsvtabbar.h"
#include "../../DevBase/dllQLsLog/dllqlslog.h"
#include "../../DevBase/dllQLsPluginsManager/qlspluginsmanagerpool.h"

static const int STACKEDWIDGET_MIN_WIDTH = 618;
static const int STACKEDWIDGET_MIN_HEIGHT = 174;

QLsPluginsManagerAppfwk::QLsPluginsManagerAppfwk(QWidget *parent) :
	QTabWidget(parent),
	pluginsManagerTableWidget(new QLsPluginsManagerTableWidget),
	hTabBar(new QTabBar),
	vTabBar(new QLsVTabBar),
	m_tabWidgetMiniWidth(STACKEDWIDGET_MIN_WIDTH),
	m_tabWidgetMiniHeight(STACKEDWIDGET_MIN_HEIGHT),
	m_isShowPluginsManagerTab(false),
	m_tabStyle(QLsTabStyle::NORTH),
	m_bHideTabBar(false)
{
	/* 主界面初始化 */
	HomeInit();
}

QLsPluginsManagerAppfwk::~QLsPluginsManagerAppfwk()
{
	QLsPluginsManagerPool::GetInstance().
			DestroyPluginsManager(
				QLsPluginsManagerPool::GetInstance().
				GetPluginsManagerByPluginsDir(m_pluginsDir)
				);

	delete pluginsManagerTableWidget;
}

QLsPluginsManagerAppfwk::QLsTabStyle QLsPluginsManagerAppfwk::tabStyle() const
{
	return m_tabStyle;
}

void QLsPluginsManagerAppfwk::setTabStyle(const QLsTabStyle &tabStyle)
{
	if(m_tabStyle == tabStyle) return;

	QSize changeSize(0, 0);					/* 样式修改前尺寸 */
	switch (tabStyle)
	{
	case QLsTabStyle::NORTH:			/* 北(正常) */
	{
		switch (m_tabStyle) {
//		case QLsTabStyle::NORTH:
//			break;
		/* 从左右变为上下 */
		case QLsTabStyle::WEST:
		{
			int preWidth = tabBar()->width();
			setTabBar(hTabBar);
			setTabPosition(QTabWidget::North);
			tabBar()->adjustSize();
			adjustSize();
			changeSize.setWidth(-preWidth);
			changeSize.setHeight(tabBar()->height());
			break;
		}
		default:
			break;
		}
		break;
	}
	case QLsTabStyle::WEST:				/* 西(左侧 竖排 文字横向) */
	{
		switch (m_tabStyle) {
		/* 从上下变为左右 */
		case QLsTabStyle::NORTH:
		{
			int preHeight = tabBar()->height();
			setTabBar(vTabBar);
			setTabPosition(QTabWidget::West);
			tabBar()->adjustSize();
			adjustSize();
			changeSize.setWidth(tabBar()->width());
			changeSize.setHeight(-preHeight);
			break;
		}
//		case QLsTabStyle::WEST:
//			break;
		default:
			break;
		}
		break;
	}
	default:
		break;
	}

	/* 更新最小尺寸 */
	if(changeSize.width() || changeSize.height())
	{
		m_tabWidgetMiniWidth += changeSize.width();
		m_tabWidgetMiniHeight += changeSize.height();
		setMinimumSize(m_tabWidgetMiniWidth, m_tabWidgetMiniHeight);
		resize(qMax(width(), m_tabWidgetMiniWidth), qMax(height(), m_tabWidgetMiniHeight));
		emit sigChangeMinimumSize(changeSize);
	}

	m_tabStyle = tabStyle;
}

/* 当前主题名 */
QString QLsPluginsManagerAppfwk::curThemeName() const
{
	return m_curThemeName;
}

void QLsPluginsManagerAppfwk::setCurThemeName(const QString &curThemeName)
{
	m_curThemeName = curThemeName;
}

/* 插件路径 */
QString QLsPluginsManagerAppfwk::pluginsDir() const
{
	return m_pluginsDir;
}

void QLsPluginsManagerAppfwk::setPluginsDir(const QString &pluginsDir)
{
	if(m_pluginsDir == pluginsDir) return;
	m_pluginsDir = pluginsDir;
	m_pluginsIniDir = QString("ini/%1.ini").arg(pluginsDir);

	/* 获取本地插件信息 */
	QLsPluginsManager *pluginsManager = QLsPluginsManagerPool::GetInstance().
			GetPluginsManagerByPluginsDir(m_pluginsDir);
	pluginsManager->RefreshLocalPlugins();

	/* 初始化隐藏插件管理器界面 */
	QSettings settings(m_pluginsIniDir, QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
	settings.beginGroup("pluginsManager");
	setIsShowPluginsManagerTab(settings.value("show", 0).toUInt());
	setBHideTabBar(settings.value("hideTabBar", 0).toUInt());
	settings.endGroup();
}

/* 插件信息配置文件路径 */
QString QLsPluginsManagerAppfwk::pluginsIniDir() const
{
	return m_pluginsIniDir;
}

/* 获取插件管理器类接口 */
QLsPluginsManagerTableWidget *QLsPluginsManagerAppfwk::GetPluginsManagerTableWidget()
{
	return pluginsManagerTableWidget;
}

/* 获取插件窗口 */
QWidget *QLsPluginsManagerAppfwk::GetPluginsWidgetByIndex(int index)
{
	return widget(index);
}

QWidget *QLsPluginsManagerAppfwk::GetPluginsWidgetByPluginsName(const QString &pluginsName)
{
	return widget(m_pluginsNameList.indexOf(pluginsName));
}

/* 加载全部插件 */
void QLsPluginsManagerAppfwk::LoadAllPlugin()
{
	/* 初始化加载全部插件 */
	QLsPluginsManager *pluginsManager = QLsPluginsManagerPool::GetInstance().
			GetPluginsManagerByPluginsDir(m_pluginsDir);
	QSettings settings(m_pluginsIniDir, QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
	foreach (PluginInfo info, pluginsManager->GetPluginsList())
	{
		settings.beginGroup(info.m_filename.toUtf8().data());
		if(settings.value("loaded", 0).toUInt())
			slotPluginLoad(info);
		pluginsManagerTableWidget->AddPluginWidget(info);
		settings.endGroup();
	}

	/* 检查插件 */
	if(!pluginsManager->CheckMustLoadPlugins())
		foreach (QString mustLoadPlugin, pluginsManager->mustLoadButDisload())
		{
			QLOG_INFO() << "加载插件" << mustLoadPlugin << "失败";
		}
}

/* 是否显示插件管理器界面 */
bool QLsPluginsManagerAppfwk::isShowPluginsManagerTab() const
{
	return m_isShowPluginsManagerTab;
}

void QLsPluginsManagerAppfwk::setIsShowPluginsManagerTab(bool isShowPluginsManagerTab)
{
	if(m_isShowPluginsManagerTab == isShowPluginsManagerTab) return;
	m_isShowPluginsManagerTab = isShowPluginsManagerTab;

	if(m_bHideTabBar) m_isShowPluginsManagerTab = false;

	/* 显示 */
	if(m_isShowPluginsManagerTab)
	{
//		QSize tabBarPreSize(tabBar()->size());
		QFontMetrics nameFontWidth(tabBar()->font());
		QString nameElideNote = nameFontWidth.elidedText(
					tr("插件管理"),
					Qt::ElideRight,
					60 * 1
					);

		insertTab(0, pluginsManagerTableWidget, QIcon("icon/plugins/manager-8A8A8A.png"), nameElideNote);
		setTabToolTip(0, tr("插件管理"));
		m_pluginsNameList.insert(0, "插件管理");
//		UpdateMinimumSize(tabBarPreSize);
	}
	/* 隐藏 */
	else
	{
		removeTab(0);
		m_pluginsNameList.removeAt(0);
	}
}

/* 主题管理器 */
QLsThemesManager *QLsPluginsManagerAppfwk::themesManager() const
{
	return QLsPluginsManagerPool::GetInstance().
			GetPluginsManagerByPluginsDir(m_pluginsDir)->themesManager();
}

/* 加载、卸载插件的槽函数 */
void QLsPluginsManagerAppfwk::slotPluginLoad(PluginInfo &pluginInfo)
{
	QLsPluginsManager *pluginsManager = QLsPluginsManagerPool::GetInstance().
			GetPluginsManagerByPluginsDir(m_pluginsDir);

	/* 卸载插件 */
	if(pluginInfo.m_isLoaded)
	{
		/* 移除工具按钮和堆栈窗口 */
		RemoveWindows(pluginInfo);

		/* 卸载插件 */
		if(!pluginsManager->UnloadPlugin(pluginInfo))
		{
			/* 卸载失败，再把 工具按钮和堆栈窗口 挂回去 */
			PopulateWindows(pluginInfo);
			QLOG_WARN() << "卸载插件" << pluginInfo.m_interfaceInfo->m_name.toUtf8().data() << "失败";
			return;
		}

		QLOG_INFO() << "卸载插件" << pluginInfo.m_interfaceInfo->m_name.toUtf8().data() << "成功";
	}
	/* 加载插件 */
	else
	{
		/* 加载插件 */
		if(!pluginsManager->LoadPlugin(pluginInfo))
		{
			/* 加载失败 */
			QLOG_WARN() << "加载插件" << pluginInfo.m_interfaceInfo->m_name.toUtf8().data() << "失败";
			return;
		}

		/* 生成工具按钮和堆栈窗口 */
		PopulateWindows(pluginInfo);

		QLOG_INFO() << "加载插件" << pluginInfo.m_interfaceInfo->m_name.toUtf8().data() << "成功";
	}

	/* 更新加载状态 */
	emit sigLoadRes(pluginInfo);
}

/* 插件的最小尺寸变化的槽函数 */
void QLsPluginsManagerAppfwk::slotPluginsChangeMinimumSize()
{
	/* 更新最新尺寸 */
	UpdateMinimumSize();
}

/* 主界面初始化 */
void QLsPluginsManagerAppfwk::HomeInit()
{
	hTabBar->setStyleSheet(
				"QTabBar::tab{"
				"min-height: 25px;"
				"min-width: 60px;"
				"}");
	setTabBar(hTabBar);

	/* 嵌入窗口大小初始化，重设大小，解决 qss样式更改 及 代码初始化 导致的窗口大小嵌入冲突 */
	if(width() < m_tabWidgetMiniWidth || height() < m_tabWidgetMiniHeight)
		resize(m_tabWidgetMiniWidth, m_tabWidgetMiniHeight);

	connect(pluginsManagerTableWidget, &QLsPluginsManagerTableWidget::sigLoad,
			this, &QLsPluginsManagerAppfwk::slotPluginLoad);
	connect(this, &QLsPluginsManagerAppfwk::sigLoadRes,
			pluginsManagerTableWidget, &QLsPluginsManagerTableWidget::slotLoadRes);
}

/* 填充插件窗口 */
void QLsPluginsManagerAppfwk::PopulateWindows(const PluginInfo &info)
{
	/* ----- 界面 ----- */
	QWidget *widget = info.m_interface->GetPluginWidget();

	/* 过长显示省略号 */
	QFontMetrics nameFontWidth(tabBar()->font());
	QString nameElideNote = nameFontWidth.elidedText(
				info.m_interfaceInfo->m_name,
				Qt::ElideRight,
				60 * 1
				);

	addTab(widget, QIcon(info.m_interfaceInfo->m_logoPath), nameElideNote);
	setTabToolTip(count() - 1, info.m_interfaceInfo->m_name);
	m_pluginsNameList.append(info.m_interfaceInfo->m_name);

	/* 主题信号槽关联并发送当前主题 */
	QLsThemesManager *themesManager = QLsPluginsManagerPool::GetInstance().
			GetPluginsManagerByPluginsDir(m_pluginsDir)->themesManager();
	info.m_interface->connetChangeTheme(themesManager);
	emit themesManager->sigChangeTheme(m_curThemeName);

	/* 绑定 最小尺寸变化 的信号槽 */
	info.m_interface->connectChangeMinimumSize(this);

	/* 更新最新尺寸 */
	UpdateMinimumSize();

	QSettings settings(m_pluginsIniDir, QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
	settings.beginGroup(info.m_filename);
	settings.setValue("logoPath", info.m_interfaceInfo->m_logoPath.toUtf8().data());
	settings.setValue("information", info.m_interfaceInfo->m_information.toUtf8().data());
	settings.setValue("loaded", 1);
	settings.setValue("level", info.m_interfaceInfo->m_level);
	settings.setValue("version", info.m_interfaceInfo->m_version.toUtf8().data());
	settings.endGroup();
}

/* 移除插件窗口 */
void QLsPluginsManagerAppfwk::RemoveWindows(const PluginInfo &info)
{
	/* 移除堆栈窗口 */
	QWidget *pluginWidget = info.m_interface->GetPluginWidget();
	int index = indexOf(pluginWidget);
	removeTab(index);
	disconnect(pluginWidget, 0, 0, 0);
	m_pluginsNameList.removeAt(index);

	/* 更新最新尺寸 */
	UpdateMinimumSize();

	QSettings settings(m_pluginsIniDir, QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
	settings.beginGroup(info.m_filename);
	settings.setValue("loaded", 0);
	settings.endGroup();
}

/* 更新最新尺寸 */
void QLsPluginsManagerAppfwk::UpdateMinimumSize()
{
	/* 更新最小尺寸 最小尺寸是所有窗口中最大的尺寸 */
	tabBar()->adjustSize();
	int minWidth = STACKEDWIDGET_MIN_WIDTH;
	int minHeight = STACKEDWIDGET_MIN_HEIGHT;
	int pages = count();
	for(int i = 0; i < pages; i++)
	{
		QWidget *page = widget(i);
		minWidth = qMax(minWidth, page->minimumWidth());
		minHeight = qMax(minHeight, page->minimumHeight() + 35);
	}

	/* 子窗口尺寸变化及最小尺寸变化 */
	QSize changeSize(minWidth - m_tabWidgetMiniWidth,
					 minHeight - m_tabWidgetMiniHeight);
	m_tabWidgetMiniWidth = minWidth;
	m_tabWidgetMiniHeight = minHeight;
	switch (m_tabStyle) {
	/* 上下不增加宽高 */
	case QLsTabStyle::NORTH:
		break;
	/* 左右只增加宽度 */
	case QLsTabStyle::WEST:
		m_tabWidgetMiniWidth += tabBar()->width();
		changeSize.setWidth(changeSize.width() + tabBar()->width());
		break;
	default:
		break;
	}
	setMinimumSize(m_tabWidgetMiniWidth, m_tabWidgetMiniHeight);

	/* 大小变化的信号 */
	emit sigChangeMinimumSize(changeSize);

	/* 更新当前尺寸 */
	resize(qMax(width(), m_tabWidgetMiniWidth), qMax(height(), m_tabWidgetMiniHeight));
}

/* 是否隐藏标签栏 */
bool QLsPluginsManagerAppfwk::bHideTabBar() const
{
	return m_bHideTabBar;
}

void QLsPluginsManagerAppfwk::setBHideTabBar(bool bHideTabBar)
{
	if(m_bHideTabBar == bHideTabBar) return;
	m_bHideTabBar = bHideTabBar;

	tabBar()->hide();
	setIsShowPluginsManagerTab(false);
}
